
#include <BChangeEvent>
#include "IStyleDriver.h"
#include "member_BStyle.h"
#include "member_BWidget.h"

using namespace BWE;

IStyleDriver::IStyleDriver()
{

}
IStyleDriver::~IStyleDriver()
{

}

void IStyleDriver::init(const BString& text)
{
	BString head;
	BString desc;
	int pos = 0;
	while (pos < text.size())
	{
		int begin = pos;
		while (begin < text.size())
		{
			char code = text[begin];
			if (text[begin] == '{')
				break;
			begin++;
		}
		if (begin == text.size())
			break;
		int end = begin;
		while (end < text.size())
		{
			if (text[end] == '}')
				break;
			end++;
		}
		if (end > begin)
		{
			head.reset();
			text.substr(head, pos, begin);
			desc.reset();
			text.substr(desc, begin + 1, end);
			addStyle(head, desc);
		}
		pos = end + 1;
	}
	if (pos < text.size())
	{
		text.substr(desc, pos, text.size());
		addStyle(head, desc);
	}
}
void IStyleDriver::clear()
{
	_styleChunks.clear();
}
bool IStyleDriver::empty() const
{
	return _styleChunks.empty();
}

bool IStyleDriver::apply(BWidget* widget)
{
	const char* cname = widget->className();
	BStyle* style = widget_member(widget)->style;
	for (int i = 0; i < _styleChunks.size(); i++)
	{
		StyleChunk& chunk = _styleChunks[i];
		if (chunk.className != '*')
		{
			if (chunk.className.empty() && widget_member(widget)->styleDriver != this)
				continue;
			if (chunk.className.size() && chunk.className != widget->className())
				continue;
			if (chunk.name.size() && chunk.name != widget->name())
				continue;
		}
		if (!style)
		{
			style = new BStyle();
			widget_member(widget)->style = style;
		}
		style_member(style)->overlap(chunk.style);
	}
	if (style)
	{
		style_member(style)->lower = widget_member(widget)->lowerStyle();
	}
	for (int i = 0; i < widget_member(widget)->children.size(); i++)
	{
		BWidget* child = widget_member(widget)->children[i];
		apply(child);
	}
	return true;
}

void IStyleDriver::addStyle(BString& head, BString& desc)
{
	BString sub;
	_styleChunks.append(StyleChunk());
	StyleChunk& chunk = _styleChunks.last();
	if (head.size())
	{
		head.simplify();
		int name_pos = head.find('#');
		int sub_pos = head.find(":");
		int class_name_end = bMin(name_pos, sub_pos);
		head.substr(chunk.className, 0, class_name_end);
		if (name_pos < head.size())
		{
			head.substr(chunk.name, name_pos + 1, sub_pos);
		}
		if (sub_pos < head.size())
		{
			head.substr(sub, sub_pos + 1, head.size());
		}
	}
	chunk.style = new BStyle();

	desc.simplify();
	BString text;
	BString sign;
	BString value;
	int pos = 0;
	while (pos < desc.size())
	{
		int end = pos;
		while (end < desc.size())
		{
			if (desc[end] == ';')
				break;
			end++;
		}
		if (pos < end)
		{
			text.reset();
			desc.substr(text, pos, end);
			int sem_pos = text.find(':');
			if (sem_pos < text.size())
			{
				sign.reset();
				text.substr(sign, 0, sem_pos);
				if (sub.size())
				{
					sign << '-' << sub;
				}
				value.reset();
				text.substr(value, sem_pos + 1, text.size());
				sign.simplify();
				value.simplify();
				style_member(chunk.style)->analysis(sign, value);
			}
			pos = end + 1;
		}
	}
}

